package top.xunfong.redis.util;

import cn.hutool.extra.spring.SpringUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.redisson.api.RBatch;
import org.redisson.api.RBucket;
import org.redisson.api.RBucketAsync;
import org.redisson.api.RedissonClient;

import java.time.Duration;
import java.util.Set;

/**
 * @author: xunfong
 * @date: 2025/10/18 2:38
 */

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class RedisUtil {

    private static final RedissonClient redissonClient = SpringUtil.getBean(RedissonClient.class);

    /**
     * 缓存基本的对象，Integer、String、实体类等
     *
     * @param key   缓存的键值
     * @param value 缓存的值
     */
    public static <T> void setCacheObject(final String key, final T value) {
        setCacheObject(key, value, false);
    }

    /**
     * 缓存基本的对象，保留当前对象 TTL 有效期
     *
     * @param key       缓存的键值
     * @param value     缓存的值
     * @param isSaveTtl 是否保留TTL有效期(例如: set之前ttl剩余90 set之后还是为90)
     * @since Redis 6.X 以上使用 setAndKeepTTL 兼容 5.X 方案
     */
    public static <T> void setCacheObject(final String key, final T value, final boolean isSaveTtl) {
        RBucket<T> bucket = redissonClient.getBucket(key);
        if (isSaveTtl) {
            try {
                bucket.setAndKeepTTL(value);
            } catch (Exception e) {
                long timeToLive = bucket.remainTimeToLive();
                setCacheObject(key, value, Duration.ofMillis(timeToLive));
            }
        } else {
            bucket.set(value);
        }
    }

    /**
     * 缓存基本的对象，Integer、String、实体类等
     *
     * @param key      缓存的键值
     * @param value    缓存的值
     * @param duration 时间
     */
    public static <T> void setCacheObject(final String key, final T value, final Duration duration) {
        RBatch batch = redissonClient.createBatch();
        RBucketAsync<T> bucket = batch.getBucket(key);
        bucket.setAsync(value);
        bucket.expireAsync(duration);
        batch.execute();
    }

    /**
     * 存储哈希表字段
     *
     * @param key   哈希表键
     * @param field 字段名
     * @param value 字段值
     */
    public static <T> void hPut(final String key, final String field, final T value) {
        redissonClient.getMap(key).put(field, value);
    }

    /**
     * 获取哈希表字段
     *
     * @param key   哈希表键
     * @param field 字段名
     * @return 字段值
     */
    public static <T> T hGet(final String key, final String field) {
        return (T) redissonClient.getMap(key).get(field);
    }

    public static <T> Set<T> hGetAllKey(String key) {
        return (Set<T>) redissonClient.getMap(key).readAllKeySet();
    }

    /**
     * 删除键
     *
     * @param key 键名
     */
    public static void delete(final String key) {
        redissonClient.getKeys().delete(key);
    }
}
